/*****************************************************************************
*    Copyright (C) 2009 ALi Corp. All Rights Reserved.
*    
*    Company confidential and Properietary information.       
*    This information may not be disclosed to unauthorized  
*    individual.    
*    File: pvr_api.c
*   
*    Description: 
*    
*    History: 
*    Date           Athor        Version        Reason
*    ========       ========     ========       ========
*    2009/3/17      Roman         
*        
*****************************************************************************/
#include <types.h>
#include <sys_config.h>
#include <retcode.h>

#include <api/libc/string.h>
#include <api/libc/printf.h>
#include <api/libc/alloc.h>

#include <osal/osal.h>

#include <bus/tsi/tsi.h>
#include <bus/tsg/tsg.h>

#include <hld/osd/osddrv.h>
#include <hld/decv/vdec_driver.h>
#include <hld/dis/VPO.h>
#include <hld/deca/deca_dev.h>
#include <hld/deca/deca.h>
#include <hld/dmx/dmx_dev.h>
#include <hld/dmx/dmx.h>
#include <hld/snd/snd_dev.h>
#include <hld/snd/snd.h>
#include <bus/ide/ide.h>

#include <api/libc/list.h>

#include <api/libfs2/types.h>
#include <api/libfs2/errno.h>
#include <api/libfs2/dirent.h>
#include <api/libfs2/stat.h>
#include <api/libfs2/statvfs.h>
#include <api/libfs2/fcntl.h>
#include <api/libfs2/unistd.h>
#include <api/libfs2/stdio.h>

#include <api/libtsi/sec_pmt.h>
#include <api/libpub29/lib_pub27.h>
#include <api/libpub29/lib_mid27.h>
#include <api/libpub29/lib_hde.h>
#include <api/libchunk/chunk.h>
#include <api/libci/ci_plus.h>
#include <api/libtsi/sec_stt.h>
#include <api/libtsi/sec_tdt2.h>
#include <api/libttx/lib_ttx.h>
#include <api/libsubt/lib_subt.h>
#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
#include <api/libisdbtcc/lib_isdbtcc.h>
#endif
#include <api/libpvr/lib_pvr.h>

#define PVRA_PRINTF(...)
//#define PVRA_PRINTF libc_printf

#define HD_MPEG2_BITRATE			(1024*1024*6)	// 1Mbytes/s
UINT8 pvr_p_get_dmx_id(PVR_HANDLE handle);

#define pvr_api_return_if_fail(expr)		do{		\
	if (expr) { } else						\
   	{							\
 		PVRA_PRINTF("file %s: line %d: assertion `%s' failed\n",	\
			__FILE__,					\
			__LINE__,					\
			#expr);						\
		return;						\
   	};		}while(0)

#define pvr_api_return_val_if_fail(expr, val)	do{		\
	if (expr) { } else						\
	{							\
		PVRA_PRINTF("file %s: line %d: assertion `%s' failed\n",	\
			__FILE__,					\
			__LINE__,					\
			#expr);						\
		return (val);						\
	};		}while(0);

struct api_dev
{
	struct dmx_device *dmx_dev[3];
};

typedef struct
{
	PPVR_CFG eng_info;
	PPVR_MGR_CFG mgr_info;
	struct api_dev dev;
	struct ListInfo play_list_info;

	int play_chan_using_tsg;
	int play_channel_using_tsg;
	BOOL  use_scramble_mode;
	UINT8 ttx_en;
	UINT8 subt_en;
	UINT8 isdbtcc_en;
	UINT8 dmx_rcd_all_data;
	UINT8 use_dmx_rcd_all_data;
	char m_pvr_prex_name[3+C_PVR_ROOT_DIR_NAME_SIZE]; // eg. "/C/ALIDVRS2"
	char m_pvr_mnt_name[3+C_PVR_ROOT_DIR_NAME_SIZE]; // eg. "/C"
}PVR_API_INFO, *PPVR_API_INFO;

static PVR_API_INFO m_pvr_info;
static UINT8 TSA;
static UINT8 TSB;
static struct dmx_device *g_dmx_dev, *g_dmx_dev2, *g_dmx_dev3;
int default_route_tsi = TSI_SPI_0;
UINT8 default_tsi_polarity = 0x03;

//for ci_tsg patch v2
#if (defined(CI_STREAM_PASS_MATCH_CARD)||defined(CC_USE_TSG_PLAYER))
#ifndef CI_SLOT_DYNAMIC_DETECT
extern UINT32 g_pvr_pmt_count;
extern INT32 pvr_pmt_callback(UINT8 *section, INT32 length, UINT32 param);
#endif
#endif

static UINT8 __get_logo_addr(UINT32 id,UINT32* addr,UINT32* len)
{
	INT32 ret;
	CHUNK_HEADER chuck_hdr;

	ret = sto_get_chunk_header(id,&chuck_hdr);
	if(ret==0)
		return 0;

	*addr = (UINT32)sto_chunk_goto(&id,0xFFFFFFFF,1) + CHUNK_HEADER_SIZE;
	*len = chuck_hdr.len - CHUNK_HEADER_SIZE + CHUNK_NAME;

	return 1;
}

static RET_CODE __pvr_dev_showlogo(UINT32 logo_id)
{
	int i;    
	void* pWriteBuffer;
	UINT32 uSizeGot;
	RET_CODE ret_code;
	UINT32 addr,len;    
	struct sto_device* sto_flash_dev = (struct sto_device *)dev_get_by_id(HLD_DEV_TYPE_STO, 0);
	struct VDec_StatusInfo videoStatus;
	struct vdec_device * p_vdec_handle = (struct vdec_device *)dev_get_by_id(HLD_DEV_TYPE_DECV, 0);

	if(__get_logo_addr(logo_id,&addr,&len) ==0 )
	{
		PVRA_PRINTF("ERROR: logo (id = %d) = 0\n", logo_id);
		
		return RET_FAILURE;
	}

	if(is_cur_decoder_avc())
    {
        h264_decoder_select(0, hde_get_mode() == VIEW_MODE_PREVIEW);
    }
	
	vdec_start(p_vdec_handle);
	
	vdec_sync_mode(p_vdec_handle, VDEC_SYNC_FREERUN,0);  

	for(i=0;i<2;i++)
	{
		ret_code = vdec_vbv_request(p_vdec_handle, len,	&pWriteBuffer,&uSizeGot,NULL);

		sto_get_data(sto_flash_dev, (UINT8 *)pWriteBuffer, addr, uSizeGot);
		vdec_vbv_update(p_vdec_handle, uSizeGot);
		PVRA_PRINTF("logo ...\n");
	}

	while(1)
	{
		vdec_io_control(p_vdec_handle, VDEC_IO_GET_STATUS, (UINT32)&videoStatus);
		if(videoStatus.uFirstPicShowed)
			break;
	}

	vdec_sync_mode(p_vdec_handle, VDEC_SYNC_PTS,VDEC_SYNC_I|VDEC_SYNC_P|VDEC_SYNC_B);  

	ret_code = vdec_stop(p_vdec_handle, FALSE, FALSE);
	if (ret_code == RET_BUSY)
	{
		ret_code = vdec_stop(p_vdec_handle, FALSE, FALSE);			
	}

	return RET_SUCCESS;
}	

int pvr_get_project_mode()
{
    return m_pvr_info.eng_info->prj_mode;
}

int pvr_get_with_tsg_using_status()
{
    return m_pvr_info.play_channel_using_tsg;
}

void pvr_set_with_tsg_using_status(int using_tsg)
{
    m_pvr_info.play_channel_using_tsg = using_tsg;
}

void pvr_r_set_scramble(void)
{
	m_pvr_info.use_scramble_mode = 1;
}

void pvr_r_set_scramble_ext(BOOL scramble)
{
	m_pvr_info.use_scramble_mode = scramble;
}

BOOL pvr_r_get_scramble(void)
{
	return m_pvr_info.use_scramble_mode;
}

void pvr_r_set_record_ttx(UINT8 ttx_en)
{
	m_pvr_info.ttx_en = ttx_en;
}

void pvr_r_set_record_subt(UINT8 subt_en)
{
	m_pvr_info.subt_en = subt_en;
}
#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
void pvr_r_set_record_isdbtcc(UINT8 isdbtcc_en)
{
	m_pvr_info.isdbtcc_en = isdbtcc_en;
}
#endif
static void tsg_play_task_loop(void)
{
#ifdef CI_SLOT_DYNAMIC_DETECT
	if(pvr_get_with_tsg_using_status())
       	cc_tsg_ci_slot_detect();
#endif
}

static void tsg_play_task_set_packet_num(UINT32 packet_num)
{
#ifdef CI_SLOT_DYNAMIC_DETECT
	if(pvr_get_with_tsg_using_status())
		cc_tsg_ci_slot_data_received(packet_num);
#endif	
}



RET_CODE  pvr_attach(PPVR_MGR_CFG cfg, PPVR_CFG ini_param)
{
    RET_CODE ret = RET_FAILURE;
	UINT8 i=0;
    
    pvr_dmx_delay_set_front(0xff, 0xff);//set Invail Value for Delay
	if(cfg == NULL || ini_param == NULL)
	{
        ret = RET_FAILURE;
        return ret;
	}
    else
    {
    	if(ini_param->play_task_loop == NULL)
    	{
    		ini_param->play_task_loop = tsg_play_task_loop;
    	}

    	if(ini_param->play_task_set_packet_num == NULL)
    	{
    		ini_param->play_task_set_packet_num = tsg_play_task_set_packet_num;

    	}

    	if(pvr_mgr_attach(cfg, ini_param) == RET_SUCCESS)
    	{
            ret = RET_SUCCESS;
    		ret |= pvr_mgr_get_cfg(&m_pvr_info.mgr_info);
    		ret |= pvr_eng_get_cfg(&m_pvr_info.eng_info);

    		for(i = 0; i < 3; i++)
    		{
    			m_pvr_info.dev.dmx_dev[i] = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, i);
    		}
            g_dmx_dev = (struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 0);
        	g_dmx_dev2 =(struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 1);
        	g_dmx_dev3 =(struct dmx_device *)dev_get_by_id(HLD_DEV_TYPE_DMX, 2);
                    
    	}
    }
	return ret;
}

RET_CODE pvr_detach(void)
{
    if(TRUE == pvr_mgr_detach())
    {
        return RET_SUCCESS;
    }
    else
    {
        return RET_FAILURE;
    }
}
// ****************************************************************
// Summary
//     Initiates the DVR module
// Description
//     This function registers the DVR module to the middle layer
//     task. Before use any DVR API, you must call this function to
//     initialize the DVR module.
//     
//     The initial process of the DVR module is as following:
//         * To initialize the IDE bus and attach the hard disk
//         * To initialize the navigation data
//         * To initialize the cache for streaming
//         * To initialize the decoding drivers
//         * To register the message handle function and the DVR
//           message to the middle layer task.
//     Once any initial step failed, this function will return the
//     failure value. The DVR module is invariable. All the DVR
//     function is invalid!
// Returns
//     If all the initial processes are succeeds, the return value
//     is SUCCESS. And if any initial process is failed, the return
//     value is FAILED.
// See Also
//     pvr_cleanup                                                 
// ****************************************************************


/*	QPSK TSG		*/ //deflaut route 0
/*    |   \				*/
/*    |    CI			*/
/*    |     \			*/
/*	TSB TSA			*/
/*    |        \			*/
/*    |          \			*/
/*    DMX1   DMX0		*/
/*            /\			*/
/*            ||			*/
/*            \ /			*/
/*	QPSK  TSG		*/ //normal rec & tms route 1
/*    |   \				*/
/*    |    CI			*/
/*    |     \			*/
/*	TSB  TSA			*/
/*          //   \			*/
/*         //     \		*/
/*    DMX1   DMX0		*/
/*    (Rec)    (Tms)		*/
/*            /\			*/
/*            ||			*/
/*            \ /			*/
/*	QPSK  TSG		*/ //TSG playback route 2
/*    |   	  //			*/
/*    |    CI			*/
/*    |     \			*/
/*	TSB  TSA			*/
/*    ||        \			*/
/*    ||         \			*/
/*    DMX1   DMX0		*/
/*    (Rec)    (Playback)	*/


void pvr_set_route(UINT8 old_route, UINT8 new_route)
{
	if(pvr_get_project_mode()&(PVR_DVBS2|PVR_ATSC))
	{
		tsi_dmx_src_select(TSI_DMX_1, TSI_TS_B);
		if((old_route == 1) && (new_route == 2))
		{
			tsi_dmx_src_select(TSI_DMX_0, TSI_TS_A);
			//normal rec & tms route---->TSG playback route
			tsi_mode_set(TSI_SPI_TSG, 0x83);
			tsi_select(TSI_DMX_0, TSI_SPI_TSG);
		}
		else if((old_route == 2) && (new_route == 1))
		{
#ifdef CC_USE_TSG_PLAYER
			tsi_dmx_src_select(TSI_DMX_0, TSI_TS_B);
#endif
			tsi_select(TSI_DMX_0, default_route_tsi);
		}
	}
	else if(pvr_get_project_mode()&PVR_DVBT)
	{
		if(m_pvr_info.use_scramble_mode)	// record scramble program as scramble.
		{
			tsi_dmx_src_select(TSI_DMX_0, TSI_TS_A);
			tsi_dmx_src_select(TSI_DMX_1, TSI_TS_B);

			if((old_route == 1) && (new_route == 2))
			{
				//normal rec & tms route---->TSG playback route
				tsi_mode_set(TSI_SPI_TSG, 0x83);
				tsi_select(TSI_DMX_0, TSI_SPI_TSG);
			}
			else if((old_route == 2) && (new_route == 1))
			{
				tsi_select(TSI_DMX_0, default_route_tsi);
			}
			
		}
		else // record scramble program as descramble.
		{
			// current needn't switch the tsi, since all data is descrambled.
			tsi_dmx_src_select(TSI_DMX_0, TSI_TS_A);
			tsi_dmx_src_select(TSI_DMX_1, TSI_TS_A);
		}
	}
	else if(pvr_get_project_mode()&(PVR_DVBT_2M))
	{

	}
}

PVR_HANDLE pvr_r_open(struct record_prog_param *prog_info)
{
	UINT8 i = 0;
	PVR_HANDLE handle;
	UINT16 dmx_id = prog_info->dmx_id;
	UINT16 bitrate_dmx_id = prog_info->live_dmx_id;
	BOOL check_ecm_emm = TRUE;
	BOOL is_scramble = (prog_info->ca_mode || prog_info->is_scrambled);
	UINT32 bitrate;
	pvr_mgr_record_param mgr_param;

	MEMSET(&mgr_param, 0, sizeof(pvr_mgr_record_param));
	mgr_param.full_path = prog_info->full_path;
	prog_info->full_path = 1;
	prog_info->pid_info.cur_audio_pid_sel = prog_info->cur_audio_pid_sel;

#ifndef NEW_DEMO_FRAME		
	if(pvr_get_project_mode()&PVR_ATSC)
	{
		check_ecm_emm = FALSE;
	}

	if(pvr_get_project_mode()&PVR_DVBT_2M)	
	{
		bitrate_dmx_id = 0;
	}
	else if(pvr_get_project_mode()&PVR_DVBT)
	{
		bitrate_dmx_id = lib_nimng_get_nim_play()-1;
	}
	else if(pvr_get_project_mode()&(PVR_DVBS2|PVR_ATSC))
	{
		bitrate_dmx_id = 0;
		prog_info->dmx_id = 1;
		if (prog_info->ca_mode)
		{
			m_pvr_info.use_scramble_mode = prog_info->is_scrambled;
			libc_printf("set scramble mode to %d\n", m_pvr_info.use_scramble_mode);
			if (prog_info->is_scrambled)
				prog_info->dmx_id = 1;
			else
				prog_info->dmx_id = 0; // record CA program as descramble
		}
	}
#endif
	for (i = 0; i < 100; ++i) // try several times
	{
		dmx_io_control(m_pvr_info.dev.dmx_dev[bitrate_dmx_id], GET_PROG_BITRATE, (UINT32)&bitrate);
		if (bitrate != 0)  // when using CI patch, bitrate may be 0
			break;
		osal_task_sleep(10);
	}

	if (prog_info->rec_special_mode == RSM_CAS9_RE_ENCRYPTION ||
     prog_info->rec_special_mode == RSM_CAS9_MULTI_RE_ENCRYPTION ||
     prog_info->rec_special_mode == RSM_VMX_MULTI_RE_ENCRYPTION)
	{ // The performance of FF/FB depending on the accuracy of the program's bitrate got from DMX.
#define AVERAGE_BITRATE_TIMES		5
		UINT32 bitrate_sum = 0;
		for (i = 0; i < AVERAGE_BITRATE_TIMES; ++i)
		{
			dmx_io_control(m_pvr_info.dev.dmx_dev[bitrate_dmx_id], GET_PROG_BITRATE, (UINT32)&bitrate);
			bitrate_sum += bitrate;
			osal_task_sleep(150);
		}
		bitrate = bitrate_sum / AVERAGE_BITRATE_TIMES;
#undef AVERAGE_BITRATE_TIMES
	}

	if(bitrate > HD_MPEG2_BITRATE*5)
		bitrate = HD_MPEG2_BITRATE*5;
	prog_info->ts_bitrate = bitrate;

	if(m_pvr_info.use_dmx_rcd_all_data)
		prog_info->record_whole_tp_data = m_pvr_info.dmx_rcd_all_data;
#ifndef NEW_DEMO_FRAME	
	// prepare some extra pid
	if(is_scramble && check_ecm_emm)//emm is needed for playback,ecm is option
	{
		// add ecm emm pid
		while(sie_get_emm_pid(NULL) == 0)
		{
			i++;
			if(i > 10)
			{
				//return 0;
				break;
			}
			osal_task_sleep(10);
		}		

		prog_info->pid_info.ecm_pid_count = sie_get_ecm_pid(prog_info->pid_info.ecm_pids);
		prog_info->pid_info.emm_pid_count = sie_get_emm_pid(prog_info->pid_info.emm_pids);

	}
#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
	if(m_pvr_info.isdbtcc_en)
	{
		struct t_isdbtcc_lang *cclist=NULL,*pcc=NULL;
		UINT8 num;	
		if(8 != sizeof(struct t_isdbtcc_lang) )
		{
			SDBBP();
		}	
		isdbtcc_get_language(&cclist, &num);
		mgr_param.cclist = cclist;
		prog_info->pid_info.isdbtcc_pid_count = num;
		for(i=0; i<num; i++)
		{
			pcc = &cclist[i];
	    		prog_info->pid_info.isdbtcc_pids[i] = pcc->pid;
			PVRA_PRINTF("pvr_r_open(): Isdbtcc Rec(%d),pid(%d)\n", i, pcc->pid);
		}
	}
#endif

#if (TTX_ON == 1)
	if(m_pvr_info.ttx_en)
	{
		struct t_ttx_lang *ttx_list = NULL, *p_ttx = NULL;
		UINT8 num;
		UINT16 ttx_pid = 0x1fff;

		if(8 != sizeof(struct t_ttx_lang))
		{
			SDBBP();
		}

		if (prog_info->pid_info.ttx_pid_count == 1)
		{
			ttx_pid = prog_info->pid_info.ttx_pids[0];
		}

		TTXEng_GetInitLang(&ttx_list, &num);
		mgr_param.ttx_list = ttx_list;
		for(i=0; i<num; i++)
		{
			p_ttx = &ttx_list[i];
			prog_info->pid_info.ttx_pids[i] = p_ttx->pid;
		}
		prog_info->pid_info.ttx_pid_count = num;
		
		TTXEng_GetSubtLang(&ttx_list, &num);
		mgr_param.ttx_subt_list = ttx_list;
		prog_info->pid_info.ttx_subt_pid_count = num;
		for(i=0; i<num; i++)
		{
			p_ttx = &ttx_list[i];
			prog_info->pid_info.ttx_subt_pids[i] = p_ttx->pid;
			PVRA_PRINTF("ttx subt %d pid %d\n", i, p_ttx->pid);
		}
		prog_info->pid_info.ttx_subt_pid_count = num;
	}
#endif

#if (SUBTITLE_ON == 1)
	if(m_pvr_info.subt_en)
	{
		struct t_subt_lang *subt_list = NULL, *p_subt = NULL;
		UINT8 num;
		UINT16 subt_pid = 0x1fff;

		if(12 != sizeof(struct t_subt_lang) )
		{
			SDBBP();
		}

		if (prog_info->pid_info.subt_pid_count == 1)
		{
			subt_pid = prog_info->pid_info.subt_pids[0];
		}
		
		subt_get_language(&subt_list, &num);
		mgr_param.subt_list = subt_list;
		prog_info->pid_info.subt_pid_count = num;
		for(i=0; i<num; i++)
		{
			p_subt = &subt_list[i];
    		prog_info->pid_info.subt_pids[i] = p_subt->pid;
			PVRA_PRINTF("subt%d pid %d\n", i, p_subt->pid);
		}
	}
#endif
#endif
	handle = pvr_mgr_r_open(&mgr_param, prog_info);
	return handle;
}

BOOL pvr_r_close_ext(PVR_HANDLE *handle, struct record_stop_param *stop_param)
{
	BOOL ret = TRUE;
	
	ret = pvr_mgr_r_close(handle, stop_param);
	
	return ret;	
}

BOOL pvr_r_close(PVR_HANDLE *handle, BOOL sync)
{
	BOOL ret = TRUE;
	struct record_stop_param stop_param;

	MEMSET(&stop_param, 0, sizeof(struct record_stop_param));
	stop_param.sync = sync;
	ret = pvr_r_close_ext(handle, &stop_param);

	// for S2 project,the mode of recording scramble program as descramble is determined by is_scramble flag.
	if(pvr_get_project_mode()&(PVR_DVBS2|PVR_ATSC))
	{
#if (!(defined(NEW_DEMO_FRAME) && defined(CC_USE_TSG_PLAYER)))
		m_pvr_info.use_scramble_mode = 1;
#endif
	}
	return ret;	
}

UINT32 pvr_r_trans(PVR_HANDLE handle)
{
	UINT32 valid_time = 0;

	pvr_mgr_ioctl(handle,PVR_ERIO_TMS2REC, (UINT32)&valid_time, 0);
	
	return valid_time;
}

RET_CODE pvr_r_changemode(PVR_HANDLE handle)
{
	return pvr_mgr_ioctl(handle,PVR_ERIO_CHG_MODE, 0, 0);
}

BOOL pvr_r_change_PID(PVR_HANDLE handle, UINT16 pid_nums, UINT16* pids)
{
	UINT16 index;
	struct record_prog_param *prog_info = (struct record_prog_param *)pids;
	struct ListInfo *info = &m_pvr_info.play_list_info;			
    
	pvr_mgr_ioctl(handle,PVR_ERIO_CHG_PID, (UINT32)pid_nums, (UINT32)pids);
    
	if(pid_nums == 0xffff)
	{
        // to fix bug for dynamic PID, 
        // when audio PID count changed, update the list info. 
        // notice: please don't change video pid.
		index = pvr_get_index(handle);
		pvr_get_rl_info(index, info);        

		if(info->audio_count != prog_info->pid_info.audio_count)
		{
			UINT8 i;
			if(prog_info->pid_info.audio_count > info->audio_count)
			{
				for(i = info->audio_count; i < prog_info->pid_info.audio_count; i++)
				{
					// only update added audio pid.
					info->pid_info.audio_pid[i] = prog_info->pid_info.audio_pid[i];
				}
			}
	        info->cur_audio_pid_sel = prog_info->pid_info.cur_audio_pid_sel;
	        info->audio_count = prog_info->pid_info.audio_count;
	        pvr_set_rl_info(index, m_pvr_info.play_list_info);            
		}       
	}
	return TRUE;
}

UINT32 pvr_r_get_time(PVR_HANDLE handle)
{
	UINT32 time;
	
	pvr_api_return_val_if_fail(handle != 0, 0);

	pvr_mgr_ioctl(handle,PVR_ERIO_GET_TIME, (UINT32)&time, 0);
	return time;
}

UINT32 pvr_r_get_ms_time(PVR_HANDLE handle)
{
	UINT32 time;
	
	pvr_api_return_val_if_fail(handle != 0, 0);

	pvr_mgr_ioctl(handle,PVR_ERIO_GET_MS_TIME, (UINT32)&time, 0);
	return time;
}

UINT8 pvr_r_get_nim_id(PVR_HANDLE handle)
{
	PREC_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_ERIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->detail.nim_id;
	return 0;
}

UINT8 pvr_r_get_dmx_id(PVR_HANDLE handle)
{
	PREC_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_ERIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->detail.r_dmx_id;
	return 0;
}

UINT32 pvr_r_get_channel_id(PVR_HANDLE handle)
{
	PREC_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_ERIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->detail.channel_id;
	return 0;
}

BOOL pvr_r_check_tms_in_same_prog()
{
	BOOL ret = FALSE;
	TMS_INFO info;

	if(pvr_mgr_ioctl(0,PVR_ERIO_GET_TMS_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		ret = info.tms_cross_prog;

	return ret;
}

RET_CODE	pvr_r_pause(PVR_HANDLE handle)
{
	return pvr_mgr_ioctl(handle, PVR_ERIO_PAUSE, 0, 1);	
}

RET_CODE	pvr_r_resume(PVR_HANDLE handle)
{
	return pvr_mgr_ioctl(handle, PVR_ERIO_RESUME, 0, 1);	
}

PVR_STATE pvr_r_get_state(PVR_HANDLE handle)
{
	PVR_STATE ret = NV_STOP;
	PREC_INFO info;
	
	if(pvr_mgr_ioctl(handle,PVR_ERIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		ret = info->state.state;
	
	return ret;	
}

BOOL pvr_r_check_active(UINT16 idx)
{
	return (RET_SUCCESS == pvr_mgr_ioctl(0, PVR_MGRIO_CHECK_RECORD, 0, (0<<16)|idx));
}

BOOL pvr_p_check_active(UINT16 idx)
{
	return (RET_SUCCESS == pvr_mgr_ioctl(0, PVR_MGRIO_CHECK_PLAYBACK, 0, (0<<16)|idx));
}

UINT16 pvr_get_index(PVR_HANDLE handle)
{
	UINT32 ret = 0;

	pvr_mgr_ioctl(handle, PVR_MGRIO_RECORD_GETIDX, (UINT32)&ret, 0);

	return ret;
}

void pvr_get_path( UINT16 record_idx, char *path)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_GET_PATH, (UINT32)path, record_idx);
}
void pvr_get_rl_info(UINT16 index, struct ListInfo *info)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_GETINFO, (UINT32)info, (0<<16)|index);	
}

#ifdef CNX_1X_CSD_CERT
BOOL pvr_get_index_by_path(UINT16 * index, char * path)
{
	return (RET_SUCCESS == pvr_mgr_ioctl(0, PVR_MGRIO_GETIDX_BY_PATH, index, path));
}

BOOL pvr_set_head_key(char *path, UINT8 *buffer, UINT32 size)
{
	UINT16 index = 0;
	
	pvr_get_index_by_path(&index, path);
	
	return (RET_SUCCESS == pvr_mgr_ioctl(0, PVR_MGRIO_SECRTKEY_SET, buffer, (size<<16)|index));

}

BOOL pvr_get_head_key(char *path, UINT8 *buffer, UINT32 size)
{
	UINT16 index;
	
	pvr_get_index_by_path(&index, path);

	return (RET_SUCCESS == pvr_mgr_ioctl(0, PVR_MGRIO_SECRTKEY_GET, buffer, (size<<16)|index));
}
#endif
#if (TTX_ON ==1)
void pvr_p_set_ttx_lang(PVR_HANDLE handle)
{
	UINT16 index;
	struct ListInfo *info = &m_pvr_info.play_list_info;

	pvr_api_return_if_fail(handle != 0);	
	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	
    if(info->ttx_num)
		TTXPvr_SetInitLang(info->ttx_list, info->ttx_num);
	if(info->ttx_subt_num)
		TTXPvr_SetSubtLang(info->ttx_subt_list, info->ttx_subt_num);

}
#endif

#if (SUBTITLE_ON == 1)
void pvr_p_set_subt_lang(PVR_HANDLE handle)
{
	UINT16 index;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	
	pvr_api_return_if_fail(handle != 0);
	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	if(info->subt_num)
		subt_pvr_set_language(info->subt_list, info->subt_num);
}
#endif

#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
void pvr_p_set_isdbtcc_lang(PVR_HANDLE handle)
{
	UINT16 index;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	
	pvr_api_return_if_fail(handle != 0);
	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	if(info->isdbtcc_num)
		isdbtcc_pvr_set_language(info->isdbtcc_list, info->isdbtcc_num);
}
#endif

PVR_HANDLE pvr_p_open_ext(struct playback_param *param)
{
	PVR_HANDLE handle;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	pvr_mgr_playback_param mgr_param;

	if (param->preview_mode == 0xFF)
	{
		if(hde_get_mode() == VIEW_MODE_PREVIEW)
			param->preview_mode = 1;
		else
			param->preview_mode = 0;
	}
	
#ifndef NEW_DEMO_FRAME	
	pvr_get_rl_info(param->index, info);

	if(pvr_get_project_mode()&PVR_DVBT)
	{
		param->live_dmx_id = lib_nimng_get_nim_play()-1;
	}
	else
	{
		param->live_dmx_id = 0;
	}

#ifdef CC_USE_TSG_PLAYER
	if(pvr_get_with_tsg_using_status())
	{
		vdec_stop(get_selected_decoder(), FALSE, FALSE); // fix BUG40518 & BUG39410
    	cc_tsg_task_pause();
	}
#endif

	if((info->is_scrambled && info->ca_mode == 1) && (!sys_ic_is_M3101()))//3105 not support CI
	{
		param->dmx_id = 0;
		if((pvr_get_project_mode()&PVR_ATSC)==0)
			si_monitor_off(0xFFFFFFFF);		
		pvr_set_route(1, 2);
#ifdef CI_SLOT_DYNAMIC_DETECT
		if(pvr_get_with_tsg_using_status())
		{
			cc_tsg_set_tsg_play_flag(TRUE);
	    	cc_tsg_ci_slot_reset();
		}
#endif
	}
	else
	{
		param->dmx_id = 2;
	}
#else
	if((sys_ic_get_chip_id() == ALI_S3811))
		param->dmx_id = 2;
#endif

#ifdef CAS9_PVR_SCRAMBLED   /* ca rec scrambled --Doy.Dong, 2011-10-31*/
    param->dmx_id = 2;
#endif

#ifdef CAS7_PVR_SCRAMBLE  
    param->dmx_id = 2;
#endif

#ifdef ONE_RECODER_PVR
    if(2 != param->dmx_id)
    {
        param->dmx_id = 2;
    }
#endif
	handle = pvr_mgr_p_open(&mgr_param, param);

#ifndef NEW_DEMO_FRAME	
	// get rl info again, pvr_mgr_p_open will adjust the user data pointer.	
	pvr_get_rl_info(param->index, info);

	if(info->is_scrambled)
	{
		struct ci_device_list dev_list;
		struct ci_service_info service;
		dev_list.nim_dev = NULL;
		dev_list.dmx_dev = m_pvr_info.dev.dmx_dev[0];
		service.prog_id = param->index;
		service.video_pid = info->pid_info.video_pid;
		service.audio_pid = info->pid_info.audio_pid[info->pid_info.cur_audio_pid_sel];
        service.subt_pid = info->pid_info.subt_pids[0];
        service.ttx_pid = info->pid_info.ttx_pids[0];
//	  service.isdbtcc_pid = info->pid_info.isdbtcc_pids[0];	
#ifdef CI_SUPPORT
#if (defined CI_SLOT_DYNAMIC_DETECT)||((!defined CI_STREAM_PASS_MATCH_CARD)&&(!defined CC_USE_TSG_PLAYER))
		api_ci_start_service(&dev_list, &service, 0x03);
#else
		api_ci_start_service(&dev_list, &service, 0);
#endif
#endif

		PVRA_PRINTF("pmt_monitor: pmt_pid %d, prog_number %d\n", info->pid_pmt, info->prog_number);

		if((pvr_get_project_mode()&PVR_ATSC)==0)
		{
			pmt_monitor_on(info->pid_pmt, info->prog_number);

//for ci_tsg patch v2
#if (defined(CI_STREAM_PASS_MATCH_CARD)||defined(CC_USE_TSG_PLAYER))
#ifndef CI_SLOT_DYNAMIC_DETECT
			g_pvr_pmt_count = 0;
			si_monitor_register_pmt_cb(pvr_pmt_callback);
#endif
#endif
		}

	}
	if( info->channel_type == 1 && 
		param->start_mode != P_OPEN_VPO_NO_CTRL && 
		param->preview_mode == 0)
	{
		__pvr_dev_showlogo(RADIO_LOGO_ID);
	}

	if(hde_get_mode() == VIEW_MODE_FULL)
	{
#if (TTX_ON == 1)
		if(m_pvr_info.ttx_en)
		{
    		ttx_enable(FALSE); // fix ttx issue
    		if(info->rec_type == PVR_REC_TYPE_PS)
    		{
				TTXPvr_SetSubtLang(NULL,0);
				TTXPvr_SetInitLang(NULL,0);
    		}
    		else if(info->ttx_num || info->ttx_subt_num )
    		{
			    ttx_pvr_enable(TRUE, param->dmx_id);
			    pvr_p_set_ttx_lang(handle);
    		}
            else 
            {
                if(info->ttx_subt_num==0)
                    TTXPvr_SetSubtLang(NULL,0);
                if(info->ttx_num == 0)
                    TTXPvr_SetInitLang(NULL,0);
            }
		}
#endif

#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
	if(m_pvr_info.isdbtcc_en)
	{
		isdbtcc_enable(FALSE);
		if((info->isdbtcc_num) && (info->rec_type == PVR_REC_TYPE_TS))
		{
			isdbtcc_pvr_set_language(info->isdbtcc_list, info->isdbtcc_num);
             	isdbtcc_set_language(0);
             	isdbtcc_pvr_enable(TRUE, param->dmx_id);
		}
		else
		{
             	isdbtcc_pvr_set_language(NULL,0);    
		}
        }
#endif

#if (SUBTITLE_ON == 1)
        if(m_pvr_info.subt_en)
		{
            subt_enable(FALSE);
		    if(info->subt_num && info->rec_type == PVR_REC_TYPE_TS)
		    {
			    subt_pvr_set_language(info->subt_list, info->subt_num);
                subt_set_language(0);
                subt_pvr_enable(TRUE, param->dmx_id);
		    }
			else
		    {
                subt_pvr_set_language(NULL,0);    
		    }
        }
#endif
	}
#endif

	return handle;	
}

PVR_HANDLE pvr_p_open(UINT16 index, PVR_STATE state, UINT8 speed, UINT32 start_time, UINT8 config)
{
	struct playback_param playback_info;
	
	playback_info.index = index;
	playback_info.state = state;
	playback_info.speed = speed;
	playback_info.start_time = start_time;
	playback_info.start_mode = config;
	playback_info.dmx_id = 0xFF;
	playback_info.live_dmx_id = 0;
	playback_info.preview_mode = 0xFF;
		
	return pvr_p_open_ext(&playback_info);
}

BOOL pvr_p_close_ext(PVR_HANDLE *handle, struct playback_stop_param *stop_param)
{
	BOOL ret;
	UINT16 index;
	UINT8 dmx_id;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	UINT8 live_dmx_id = 0;
	UINT32 bReset = FALSE;
	
	pvr_api_return_val_if_fail(*handle != 0, FALSE);

#ifndef NEW_DEMO_FRAME	
	index = pvr_get_index(*handle);
	pvr_get_rl_info(index, info);
	dmx_id = pvr_p_get_dmx_id(*handle);

	if(pvr_get_project_mode()&PVR_DVBT)
	{
		live_dmx_id = lib_nimng_get_nim_play()-1;
	}
	else
	{
		live_dmx_id = 0;
	}

	static BOOL b_reopen_reset = FALSE;
	if(info->is_scrambled)
	{
		pvr_set_route(2, 1);
		b_reopen_reset = TRUE;
	}

	if (!pvr_r_get_scramble())
	{
		b_reopen_reset = FALSE;
	}
	
	if (stop_param->stop_mode == P_STOP_AND_REOPEN && b_reopen_reset)
	{
		bReset = TRUE;
		b_reopen_reset = FALSE;
	}

	if(hde_get_mode() == VIEW_MODE_FULL)
	{
#if (TTX_ON == 1)
		if(info->ttx_num || info->ttx_subt_num)
		{
			ttx_pvr_enable(FALSE, dmx_id);
		}
		//modify for ttx and epg share memory 2011 10 31
			#ifdef TTX_EPG_SHARE_MEM
			epg_off();
			epg_release();
			#endif
			//modify end
		ttx_enable(TRUE); // fix ttx issue
#endif
#if (SUBTITLE_ON == 1)
		if(info->subt_num)
		{
			subt_pvr_enable(FALSE, dmx_id);
    	}
        subt_enable(TRUE);
#endif

#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
	if(info->isdbtcc_num)
		{isdbtcc_pvr_enable(FALSE, dmx_id);}
	isdbtcc_enable(TRUE);
#endif


	}

	if(dmx_id < 2) //use tsg to playback
	{
#ifdef CI_SUPPORT
		PVRA_PRINTF("stop ci, pmt_monitor off: pmt_pid %d\n", info->pid_pmt);
		api_ci_stop_service(NULL, NULL, 0x03);
#endif
		if((pvr_get_project_mode()&PVR_ATSC)==0)
		{
			pmt_monitor_off(info->pid_pmt);
		}
	}
#endif

	ret = pvr_mgr_p_close(handle, stop_param);

#ifndef NEW_DEMO_FRAME	
#ifndef PUB_PORTING_PUB29
	if(stop_param->sync)
	{
		if(info->is_scrambled)
		{
#ifdef CI_SLOT_DYNAMIC_DETECT
			if(pvr_get_with_tsg_using_status())
				cc_tsg_set_tsg_play_flag(FALSE);
#endif
		}
		
		if(stop_param->stop_mode == P_STOPPED_ONLY)
		{
#ifdef CC_USE_TSG_PLAYER
			if(pvr_get_with_tsg_using_status())
            	cc_tsg_task_resume(FALSE);
#endif
		}
		else if(stop_param->stop_mode == P_STOP_AND_REOPEN)
		{

			if(stop_param->reopen_handle == 0)
			{
				// no recorder,	pvr module cann't know what channel will be played
				// so, let ap layer start playing channel.
#ifdef CC_USE_TSG_PLAYER
				if(pvr_get_with_tsg_using_status())
                	cc_tsg_task_resume(!bReset);
#endif
			}
			else
			{	
				// re-set ttx.
			#if (TTX_ON == 1)
				pvr_p_set_ttx_lang(stop_param->reopen_handle);
			#endif
			#if(SUBTITLE_ON == 1)
				pvr_p_set_subt_lang(stop_param->reopen_handle);
			#endif
			
			#if (defined(ISDBT_CC)&&ISDBT_CC == 1)
				pvr_p_set_isdbtcc_lang(stop_param->reopen_handle);
			#endif
			
#ifdef CC_USE_TSG_PLAYER
				if(pvr_get_with_tsg_using_status())
				{
	                if (bReset == FALSE)
	                    bReset = cc_tsg_task_need_reset_channel();
                	cc_tsg_task_resume(!bReset);
	                if (bReset)
	                    cc_play_channel(CC_CMD_RESET_CRNT_CH,0);
				}
#else
	                if((dmx_id < 2)&&bReset) //use tsg to playback
	                {
	                    cc_play_channel(CC_CMD_RESET_CRNT_CH,0);
	                }
#endif
			}
		}		
	}
#endif //PUB_PORTING_PUB29
#endif 
	return ret;
}

BOOL pvr_p_close(PVR_HANDLE *handle, UINT8 stop_mode, UINT8 vpo_mode,BOOL sync)
{
	struct playback_stop_param stop_param;

	MEMSET(&stop_param, 0, sizeof(struct playback_stop_param));
	stop_param.stop_mode = stop_mode;
	stop_param.vpo_mode = vpo_mode;
	stop_param.sync = sync;
	stop_param.reopen_handle = pvr_eng_get_last_rec_hnd();
	
	return pvr_p_close_ext(handle, &stop_param);
}

BOOL pvr_p_restart(PVR_HANDLE handle, UINT32 param1)
{
	UINT8 dmx_id;
	UINT8 live_dmx_id;
	UINT16 index;
	PH_CHAN_INFO info;
	PPLY_INFO ply_info;
	struct playback_param playback_info;
	
	if(handle == 0)
	{
		return FALSE;
	}

	MEMSET(&playback_info, 0 , sizeof(playback_info));

	//get last info
	index = pvr_get_index(handle);
	pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&ply_info, 0);
	info = &ply_info->play_chan_info;
	printf_pid_info(&info->pid_info);

	// stop pvr manager	
	if(info->is_scrambled)
	{
		//use tsg to playback
		pvr_set_route(2, 1);
#ifdef CI_SUPPORT
		PVRA_PRINTF("stop ci, pmt_monitor off: pmt_pid %d\n", info->pid_info.pmt_pid);
		api_ci_stop_service(NULL, NULL, 0x03);
#endif
		if((pvr_get_project_mode()&PVR_ATSC)==0)
		{
			pmt_monitor_off(info->pid_info.pmt_pid);
		}
#ifdef CI_SLOT_DYNAMIC_DETECT
		if(pvr_get_with_tsg_using_status())
			cc_tsg_set_tsg_play_flag(FALSE);
#endif
	}

	// stop old player
	pvr_mgr_ioctl(handle,PVR_EPIO_RESTART, 0, 0);

	// get new channel info
	pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&ply_info, 0);
	info = &ply_info->play_chan_info;

	printf_pid_info(&info->pid_info);

#ifndef NEW_DEMO_FRAME	
	// prepare restart info
	if(pvr_get_project_mode()&PVR_DVBT)
	{			
		playback_info.live_dmx_id = lib_nimng_get_nim_play()-1;
	}
#endif

	// restart pvr manager	
	if(info->is_scrambled)
	{
		dmx_id = 0;
		if((pvr_get_project_mode()&PVR_ATSC)==0)
			si_monitor_off(0xFFFFFFFF);		
		pvr_set_route(1, 2);
#ifdef CI_SLOT_DYNAMIC_DETECT
		if(pvr_get_with_tsg_using_status())
		{
			cc_tsg_set_tsg_play_flag(TRUE);
			cc_tsg_ci_slot_reset();
		}
#endif
	}
	else
	{
		dmx_id = 2;
	}

	playback_info.dmx_id = dmx_id;
	// restart pvr engine
	pvr_mgr_ioctl(handle,PVR_EPIO_RESTART, 1, (UINT32)&playback_info);

	// start ci service
	if(info->is_scrambled)
	{
		struct ci_device_list dev_list;
		struct ci_service_info service;
		dev_list.nim_dev = NULL;
		dev_list.dmx_dev = m_pvr_info.dev.dmx_dev[0];
		service.prog_id = index;
		service.video_pid = info->pid_info.video_pid;
		service.audio_pid = info->pid_info.audio_pid[info->pid_info.cur_audio_pid_sel];
        service.subt_pid = info->pid_info.subt_pids[0];
        service.ttx_pid = info->pid_info.ttx_pids[0];
//        service.isdbtcc_pid = info->pid_info.isdbtcc_pids[0];		
#ifdef CI_SUPPORT
#if (defined CI_SLOT_DYNAMIC_DETECT)||((!defined CI_STREAM_PASS_MATCH_CARD)&&(!defined CC_USE_TSG_PLAYER))
		api_ci_start_service(&dev_list, &service, 0x03);
#else
		api_ci_start_service(&dev_list, &service, 0);
#endif
#endif
		PVRA_PRINTF("pmt_monitor: pmt_pid %d, prog_number %d\n", info->pid_info.pmt_pid, info->prog_number);

		if((pvr_get_project_mode()&PVR_ATSC)==0)
		{
			pmt_monitor_on(info->pid_info.pmt_pid, info->prog_number);

//for ci_tsg patch v2
#if (defined(CI_STREAM_PASS_MATCH_CARD)||defined(CC_USE_TSG_PLAYER))
#ifndef CI_SLOT_DYNAMIC_DETECT
#ifndef NEW_DEMO_FRAME
			g_pvr_pmt_count = 0;
			si_monitor_register_pmt_cb(pvr_pmt_callback);
#endif
#endif
#endif
		}
	}
}

BOOL pvr_p_play(PVR_HANDLE handle)
{
	UINT16 index;
	BOOL ret;
	struct ListInfo *info = &m_pvr_info.play_list_info;

	pvr_api_return_val_if_fail(handle != 0, FALSE);

	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	ret = pvr_mgr_p_play_mode(handle, NV_PLAY, 1);

#ifdef CC_USE_TSG_PLAYER
	if(info->is_scrambled && index != TMS_INDEX)
    {
		if(pvr_get_with_tsg_using_status())
        	cc_tsg_task_reset_channel(TRUE);
	}
#endif
	
	return ret;
}
                                  
BOOL pvr_p_stop(PVR_HANDLE handle)
{
	return pvr_mgr_p_play_mode(handle, NV_STOP, 0);	
}
                     
BOOL pvr_p_pause(PVR_HANDLE handle)
{
	return pvr_mgr_p_play_mode(handle, NV_PAUSE, 0);	
}

         
BOOL pvr_p_fast_forward(PVR_HANDLE handle, UINT8 speed)
{
	return pvr_mgr_p_play_mode(handle, NV_FF, speed);
}

      
BOOL pvr_p_fast_backward(PVR_HANDLE handle, UINT8 speed)
{
	return pvr_mgr_p_play_mode(handle, NV_FB, speed);
}

         
BOOL pvr_p_slow(PVR_HANDLE handle, UINT8 speed)
{
	return pvr_mgr_p_play_mode(handle, NV_SLOW, speed);
}

              
BOOL pvr_p_revslow(PVR_HANDLE handle, UINT8 speed)
{
	return pvr_mgr_p_play_mode(handle, NV_REVSLOW, speed);
}

BOOL pvr_p_step(PVR_HANDLE handle)
{
	return pvr_mgr_p_play_mode(handle, NV_STEP, 0);
}

PVR_STATE player_get_state(PVR_HANDLE handle)
{
	PPLY_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->state.state;
	return 0;	
}

PVR_STATE pvr_p_get_state(PVR_HANDLE handle)
{
	return player_get_state(handle);
}

INT8 pvr_p_get_direct(PVR_HANDLE handle)
{
	PPLY_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->state.direct;
	return 0;	
}
               
UINT8 pvr_p_get_speed(PVR_HANDLE handle)
{
	PPLY_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return info->state.speed;
	return 0;	
}

UINT8 pvr_p_get_dmx_id(PVR_HANDLE handle)
{
	PPLY_INFO info;
	if(pvr_mgr_ioctl(handle,PVR_EPIO_GET_INFO, (UINT32)&info, 0) == RET_SUCCESS)
		return (UINT8)info->detail.p_dmx_id;
	return 0;		
}

                        
BOOL pvr_p_timesearch(PVR_HANDLE handle, UINT32 ptm)
{
	if(pvr_mgr_ioctl(handle,PVR_EPIO_TIMESEARCH, ptm, 0) == RET_SUCCESS)
		return TRUE;
	return FALSE;	
}

BOOL pvr_p_jump(PVR_HANDLE handle, INT32 ptm)
{
	if(pvr_mgr_ioctl(handle,PVR_EPIO_JUMP, (UINT32)ptm, 0) == RET_SUCCESS)
		return TRUE;
	return FALSE;	
}

BOOL pvr_p_seek(PVR_HANDLE handle, UINT32 pos)
{
	if(pvr_mgr_ioctl(handle,PVR_EPIO_SEEK, pos, 0) == RET_SUCCESS)
		return TRUE;
	return FALSE;
}

BOOL pvr_p_lock_switch(PVR_HANDLE handle, UINT32 lock_en)
{
	if(pvr_mgr_ioctl(handle,PVR_EPIO_LOCK_SWITCH, lock_en, 0) == RET_SUCCESS)
		return TRUE;
	return FALSE;
}

UINT32 pvr_p_get_time(PVR_HANDLE handle)
{
	UINT32 time;
	pvr_mgr_ioctl(handle,PVR_EPIO_GET_TIME, (UINT32)&time, 0);
	return time;
}

UINT32 pvr_p_get_ms_time(PVR_HANDLE handle)
{
	UINT32 time;
	pvr_mgr_ioctl(handle,PVR_EPIO_GET_MS_TIME, (UINT32)&time, 0);
	return time;
}

void pvr_p_switch_audio_pid(PVR_HANDLE handle, UINT16 pid)
{
	UINT16 index;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	
	pvr_api_return_if_fail(handle != 0);
	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	
	pvr_mgr_ioctl(handle, PVR_EPIO_SWITCH_A_PID, (UINT32)pid, 0);
#if (SYS_PROJECT_SM == PROJECT_SM_CI)			
	//api_ci_switch_aid(index,(UINT16)info->pid_a);
    api_ci_switch_aid(index,(UINT16)pid);
#endif	
}

void pvr_p_switch_audio_pid_list(PVR_HANDLE handle, UINT16 *pid_list)
{
	UINT16 index;
	struct ListInfo *info = &m_pvr_info.play_list_info;
	
	pvr_api_return_if_fail(handle != 0);
	index = pvr_get_index(handle);
	pvr_get_rl_info(index, info);
	
	pvr_mgr_ioctl(handle, PVR_EPIO_SWITCH_A_PIDL, 0, (UINT32)pid_list);
#if (SYS_PROJECT_SM == PROJECT_SM_CI)			
    api_ci_switch_aid(index,(UINT16)pid_list[0]);
#endif	
}

void pvr_p_switch_audio_channel(PVR_HANDLE handle, UINT8 audio_channel)
{
	pvr_mgr_ioctl(handle, PVR_EPIO_SWITCH_A_CHAN, (UINT32)audio_channel, 0);
}

UINT32 pvr_p_get_pos(PVR_HANDLE handle)
{
	UINT32 pos = 0;
	pvr_mgr_ioctl(handle, PVR_EPIO_GET_POS, (UINT32)&pos, 0);	
	return pos;
}

UINT32 pvr_p_get_pos_time(PVR_HANDLE handle)
{
	UINT32 ptm = 0;	
	pvr_mgr_ioctl(handle, PVR_EPIO_GET_POS_TIME, (UINT32)&ptm, 0);	
	return ptm*10;
}

static int pvr_fs_format_hdd(UINT8 mode,char *mount_prefix, char *name)
{
	int ret;

	ret = fs_unmount(mount_prefix, 0x00000001);

	do
	{
		if(ret < 0)
		{
			PVRA_PRINTF("fs unmount failed!\n");
			break;
		}

		if(mode == 1)
		{
			ret = fs_mkfs(name, "FAT");
			if(ret < 0)
				break;
			ret = fs_mount(mount_prefix, name, "FAT", 0, NULL);
			if(ret < 0)
				break;			
		}
		else
		{
			ret = fs_mkfs(name, "NTFS");
			if(ret >= 0)
			{
				ret = fs_mount(mount_prefix, name, "NTFS", 0, NULL);
			}
		}		
	}while(0);
	return ret;
}

#ifndef DVR_PVR_SUPPORT
//This function is here to solve compile issue when undef DVR_PVR_SUPPORT on FPGA
//--Michael
void api_pvr_check_level(struct dvr_HDD_info *hdd_info)
{
}
#endif

BOOL pvr_format_multi_hdd(UINT8 mode, char *vol_path)
{
	int ret = -1;
	BOOL format_cur_pvr_partition = FALSE;

	struct dvr_HDD_info part_info;
	pvr_get_HDD_info(&part_info);

	if (vol_path == NULL)
	{
		format_cur_pvr_partition = TRUE;
	}
	else if (STRCMP(vol_path, part_info.mount_name) == 0)
	{
		format_cur_pvr_partition = TRUE;
	}

	if (format_cur_pvr_partition)
	{
		PVRA_PRINTF("clean PVR volume: %s\n", part_info.mount_name);
		pvr_tms_vol_cleanup();
	}

	if (vol_path == NULL)
	{
		// format the pvr partition
		ret = pvr_fs_format_hdd(mode, part_info.mount_name, part_info.disk_name);
	}
	else
	{
		// multi-partition support, name as "/mnt/uda1", dev_path as "/dev/uda1"
		char dev_path[16];
		STRCPY(dev_path, vol_path);
		dev_path[1] = 'd';
		dev_path[2] = 'e';
		dev_path[3] = 'v';

		ret = pvr_fs_format_hdd(mode, vol_path, dev_path);
	}
	
	// pvr reinit
	if (ret >= 0 && format_cur_pvr_partition)
	{
		PVRA_PRINTF("reinit PVR volume %s\n", vol_path);
		pvr_set_root_dir_name(vol_path);
	
		/* init PVR volume */
		if (pvr_tms_vol_init() < 0)
		{
			PVRA_PRINTF("PVR reinit failed\n");
		}
	
		
	}
	return (ret >= 0) ? TRUE : FALSE;
}

BOOL pvr_format_HDD(UINT8 mode)
{
	return pvr_format_multi_hdd(mode, NULL);
}

UINT32 pvr_get_tms_capability()
{
	TMS_INFO info;

	if(pvr_mgr_ioctl(0,PVR_ERIO_GET_TMS_INFO, (UINT32)&info, 0) == RET_SUCCESS)
	{
		return info.tms_capability;
	}	
	return 0;	
}

BOOL pvr_set_tms_size(UINT32 tms_size)
{	
	PPVR_CFG ppcfg;
	RET_CODE ret = RET_FAILURE;

	if (pvr_eng_get_cfg(&ppcfg) == RET_SUCCESS)
	{
		ret = _pvr_mgr_set_tms_size(tms_size, ppcfg->tms_file_min_size * 1024);
	}
	
	return (ret == RET_SUCCESS);
}

BOOL pvr_init_size(char *mount_name)
{	
	RET_CODE ret = RET_FAILURE;

	ret = pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_INITSIZE, (UINT32)mount_name, 0);	
	
	return ret;
}

void pvr_set_tms_level(UINT8 percent)
{
	PPVR_CFG ppcfg;

	if (pvr_eng_get_cfg(&ppcfg) == RET_SUCCESS)
	{
		_pvr_mgr_set_tms_level(percent, ppcfg->tms_file_min_size * 1024);
	}
}

void pvr_get_real_time_rw_speed(UINT32 *read_speed, UINT32 *write0_speed, UINT32 *write1_speed, UINT32 *write2_speed)
{
	pvr_eng_get_real_speed(read_speed, write0_speed, write1_speed, write2_speed);
}

void pvr_set_default_switch_route(UINT32 default_tsi,UINT8 tsi_polarity)
{
	default_route_tsi = default_tsi;
    default_tsi_polarity = tsi_polarity;
    
}

//##: Recording list management API
UINT16 pvr_get_rl_count()
{
	UINT32 ret = 0;
	
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_GETCNT, (UINT32)&ret, 0);

	return ret;
}

UINT16 pvr_get_rl_info_by_pos(UINT16 pos, struct ListInfo *info)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_GETINFO, (UINT32)info, (1<<16)|(pos+1));	
}

void pvr_set_rl_info(UINT16 rl_id, struct ListInfo info)
{	
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_SETINFO, (UINT32)&info, (0<<16)|rl_id);	
}

BOOL pvr_check_rl_del(void)
{
	UINT32 ret = 0;

	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_CHK_DEL, (UINT32)&ret, 0);

	return (ret == 1);
}

void pvr_clear_rl_del(void)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_CLR_DEL, 0, 0);
}

void pvr_save_rl(UINT16 index)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_SAVE, 0, (0<<16)|index);
}

void pvr_update_rl(void)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_RECORD_SAVE_ALL, 0, 0);
}

UINT8 pvr_get_HDD_info(struct dvr_HDD_info *partition_info)
{
	RET_CODE ret = pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_GETINFO, (UINT32)partition_info, 0);

	return (ret== RET_SUCCESS);
}

UINT8 pvr_get_tms_hdd(struct dvr_HDD_info *partition_info)
{
	RET_CODE ret = _pvr_mgr_get_tms_hdd(partition_info);
	return (ret== RET_SUCCESS);
}

//##: User data area.
UINT32 pvr_p_save_cur_pos(PVR_HANDLE handle)
{
	if(handle != 0)
		pvr_mgr_ioctl(handle, PVR_MGRIO_SAVE_CUR_POS, 0, 0);
	return 0;
}


UINT32	pvr_p_get_lastplay_pos(UINT16 index)
{
	UINT32 ret = 0;

	pvr_mgr_ioctl(0, PVR_MGRIO_GET_LAST_POSPTM, (UINT32)&ret, (0<<16)|index);

	return ret;
}

RET_CODE pvr_set_bookmark(UINT16 record_idx, UINT32 mark_time)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_BOOKMARK_SET, mark_time, (0<<16)|record_idx);
}

UINT8 pvr_get_bookmark(UINT16 record_idx, UINT32 *mark_ptm_array)
{
	UINT32 ret = (0<<16)|record_idx;
	
	pvr_mgr_ioctl(0, PVR_MGRIO_BOOKMARK_GET, (UINT32)mark_ptm_array, (UINT32)&ret);

	return ret;
}

//repeat AB
RET_CODE pvr_set_repeatmark(UINT16 record_idx, UINT32 mark_time)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_REPEATMARK_SET, mark_time, (0<<16)|record_idx);
}

UINT8 pvr_get_repeatmark(UINT16 record_idx, UINT32 *mark_ptm_array)
{
	UINT32 ret = (0<<16)|record_idx;
	
	pvr_mgr_ioctl(0, PVR_MGRIO_REPEATMARK_GET, (UINT32)mark_ptm_array, (UINT32)&ret);

	return ret;
}

RET_CODE pvr_clear_repeatmark(UINT16 record_idx)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_REPEATMARK_CLR, 0, (0<<16)|record_idx);
}

RET_CODE pvr_set_agelimit(UINT16 record_idx, UINT32 ptm, UINT32 age)
{
	record_agelimit_item item;

	item.age = age;
	item.ptm = ptm;
	return pvr_mgr_ioctl(0, PVR_MGRIO_AGELIMIT_SET, (UINT32)&item, (0<<16)|record_idx);
}

UINT8 pvr_get_agelimit(UINT16 record_idx, UINT32 ptm)
{
	record_agelimit_item item;

	item.age = 0;
	item.ptm = ptm;
	pvr_mgr_ioctl(0, PVR_MGRIO_AGELIMIT_GET, (UINT32)&item, (0<<16)|record_idx);
	
	return item.age;
}

RET_CODE pvr_set_ratingctl(UINT16 record_idx, UINT32 ptm, UINT32 ratingctl)
{
	record_ratingctl_item item;

	item.ptm = ptm;
	item.rating = ratingctl;
	return pvr_mgr_ioctl(0, PVR_MGRIO_RATINGCTL_SET, (UINT32)&item, (0<<16)|record_idx);
}

UINT32 pvr_get_ratingctl(UINT16 record_idx, UINT32 ptm)
{
	record_ratingctl_item item;

	item.ptm = ptm;
	item.rating = 0;
	pvr_mgr_ioctl(0, PVR_MGRIO_RATINGCTL_GET, (UINT32)&item, (0<<16)|record_idx);
	
	return item.rating;
}

RET_CODE pvr_set_mat_rating(PVR_HANDLE handle, UINT32 ptm, UINT32 rating)
{
	pvr_cas9_mat_rating mat_rating;
	mat_rating.ptm = ptm;
	mat_rating.rating = rating;
	return pvr_mgr_ioctl(handle, PVR_ERIO_SET_CAS9_MAT_RATING, (UINT32)&mat_rating, 0);
}

RET_CODE pvr_get_mat_rating(PVR_HANDLE handle, UINT32 ptm, UINT32 *rating)
{
	RET_CODE ret;
	pvr_cas9_mat_rating mat_rating;
	mat_rating.ptm = ptm;
	mat_rating.rating = 0;
	ret = pvr_mgr_ioctl(handle, PVR_EPIO_GET_CAS9_MAT_RATING, (UINT32)&mat_rating, 0);
	if (ret == RET_SUCCESS)
		*rating = mat_rating.rating;
	return ret;
}

RET_CODE pvr_get_mat_rating_by_idx(UINT16 record_idx, UINT32 ptm, UINT32 *rating)
{
	RET_CODE ret;
	pvr_cas9_mat_rating mat_rating;
	mat_rating.ptm = ptm;
	mat_rating.rating = 0;
	ret = pvr_mgr_ioctl(0, PVR_EPIO_GET_CAS9_MAT_RATING, (UINT32)&mat_rating, (0<<16)|record_idx);
	if (ret == RET_SUCCESS)
		*rating = mat_rating.rating;
	return ret;
}

RET_CODE pvr_set_finger_info(PVR_HANDLE handle, pvr_finger_info *finger_info)
{
	return pvr_mgr_ioctl(handle, PVR_ERIO_SET_CAS9_FINGER_PRINT, (UINT32)finger_info, 0);
}

RET_CODE pvr_get_finger_info(PVR_HANDLE handle, pvr_finger_info *finger_info)
{
	return pvr_mgr_ioctl(handle, PVR_EPIO_GET_CAS9_FINGER_PRINT, (UINT32)finger_info, 0);
}
RET_CODE pvr_set_last_play_ptm(PVR_HANDLE handle, UINT32 ptm)
{
	return pvr_mgr_ioctl(handle, PVR_EPIO_SET_CAS9_LAST_PLAY_PTM, (UINT32)ptm, 0);
}

RET_CODE pvr_get_last_play_ptm(PVR_HANDLE handle, UINT32 *ptm)
{
	return pvr_mgr_ioctl(handle, PVR_EPIO_GET_CAS9_LAST_PLAY_PTM, (UINT32)ptm, 0);
}

// DTG_PVR : event detail
RET_CODE pvr_set_event_detail(UINT16 record_idx, UINT8 *pDetail, UINT32 len, UINT8 type)
{
	record_event_detail_item item;

	item.pDetail = pDetail;
	item.len = len;
	item.type = type;
	return pvr_mgr_ioctl(0, PVR_MGRIO_EVENT_DETAIL_SET, (UINT32)&item, (0<<16)|record_idx);
}

UINT8* pvr_get_event_detail(UINT16 record_idx, UINT8 type)

{
	record_event_detail_item item;

	item.pDetail = 0;
	item.len = 0;
	item.type = type;
	pvr_mgr_ioctl(0, PVR_MGRIO_EVENT_DETAIL_GET, (UINT32)&item, (0<<16)|record_idx);
	
	return item.pDetail;
}
// DTG_PVR : event name
RET_CODE pvr_set_event_name(UINT16 record_idx, UINT8* event_name)
{
	record_event_item item;

	item.pEvent_name = event_name;
	return pvr_mgr_ioctl(0, PVR_MGRIO_EVENT_NAME_SET, (UINT32)&item, (0<<16)|record_idx);
}

UINT8* pvr_get_event_name(UINT16 record_idx)
{
	record_event_item item;

	item.pEvent_name = 0;
	pvr_mgr_ioctl(0, PVR_MGRIO_EVENT_NAME_GET, (UINT32)&item, (0<<16)|record_idx);
	return item.pEvent_name;
}
//#endif

RET_CODE pvr_set_ca_cw(UINT16 record_idx, UINT32 ptm, UINT8 *eCW, UINT8 *oCW)
{
	record_ca_cw_item item;

	item.ptm = ptm;
	item.eCW = eCW;
	item.oCW = oCW;

	return pvr_mgr_ioctl(0, PVR_MGRIO_CACW_SET, (UINT32)&item, (0<<16)|record_idx);
}

RET_CODE pvr_get_ca_cw(UINT16 record_idx, UINT32 ptm, UINT8 *eCW, UINT8 *oCW)
{
	record_ca_cw_item item;

	item.ptm = ptm;
	item.eCW = eCW;
	item.oCW = oCW;
	
	return pvr_mgr_ioctl(0, PVR_MGRIO_CACW_GET, (UINT32)&item, (0<<16)|record_idx);
}

void pvr_dump_ca_cw(UINT16 record_idx)
{
	pvr_mgr_ioctl(0, PVR_MGRIO_CACW_DUMP, 0, (0<<16)|record_idx);
}

RET_CODE pvr_set_audio_type(UINT16 record_idx, UINT8 *buf, UINT8 len)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_AUDIO_TYPE_SET, (UINT32)buf, (len<<24)|(0<<16)|record_idx);
}

RET_CODE pvr_get_audio_type(UINT16 record_idx, UINT8 *buf, UINT8 len)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_AUDIO_TYPE_GET, (UINT32)buf, (len<<24)|(0<<16)|record_idx);
}

int pvr_tms_vol_cleanup(void)
{
 	struct pvr_clean_info param;

	param.disk_mode = 0;
	STRCPY(param.mount_name, m_pvr_info.m_pvr_mnt_name);
	return pvr_cleanup_partition(&param);
}

RET_CODE pvr_set_disk_use(UINT8 use, const char *mount_name)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_SETUSEAGE, (UINT32)mount_name, use);
}

INT8 pvr_get_disk_mode(char *mount_name)
{
	INT8 ret = -1;
	BOOL rec_disk = FALSE, tms_disk = FALSE;
	enum PVR_DISKMODE pvr_mode;
	char rec[16], tms[16];

	pvr_mode = pvr_get_cur_mode(rec, tms);
	rec_disk = (STRLEN(rec) != 0) && (!STRCMP(mount_name, rec));
	tms_disk = (STRLEN(tms) != 0) && (!STRCMP(mount_name, tms));
	if(rec_disk && tms_disk)
		ret = PVR_REC_AND_TMS_DISK;
	else if(rec_disk)
		ret = PVR_REC_ONLY_DISK;
	else if(tms_disk)
		ret = PVR_TMS_ONLY_DISK;

	return ret;
}

enum PVR_DISKMODE pvr_get_cur_mode(char *rec_partition, char *tms_partition)
{
	enum PVR_DISKMODE ret;
	
	pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_GETREC, (UINT32)rec_partition, 0);
	pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_GETTMS, (UINT32)tms_partition, 0);
	pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_GETMODE, (UINT32)&ret, 0);

	return ret;
}

int pvr_tms_vol_init(void)
{
	struct pvr_register_info info;

	STRCPY(info.mount_name, m_pvr_info.m_pvr_mnt_name);
	info.disk_mode = 0;
	info.disk_usage = PVR_REC_AND_TMS_DISK;
	info.init_list = 1;
	info.check_speed = 1;
	info.sync = 1;

	return pvr_register_partition(&info);
}

void pvr_resume_play_channel(void)
{
}

void pvr_r_set_record_all(BOOL bRecordAll)
{
	m_pvr_info.use_dmx_rcd_all_data = 1;
    m_pvr_info.dmx_rcd_all_data = bRecordAll;
}

BOOL pvr_r_get_record_all(void)
{
    return m_pvr_info.dmx_rcd_all_data;
}

void pvr_check_disk(void)
{
	struct dvr_HDD_info partition_info;
	pvr_get_HDD_info(&partition_info);
	pvr_mgr_ioctl(0, PVR_MGRIO_PARTITION_TEST, 0, (UINT32)partition_info.mount_name);
}

char *pvr_get_pvr_root_dir_name(void)
{
  	return NULL;
}

// get the directory such as "/C/AliDVBS2", or "/mnt/uda1/AliDVBS2"
char *pvr_get_root_dir_name(void)
{
	_pvr_mgr_calc_fullpath(m_pvr_info.m_pvr_mnt_name, NULL, PVR_TYPE_PREX, 0, m_pvr_info.m_pvr_prex_name);
   	return m_pvr_info.m_pvr_prex_name;
}

// set the directory such as "/C/AliDVBS2", or "/mnt/uda1/AliDVBS2"
BOOL pvr_set_root_dir_name(char *name)
{	
	_pvr_mgr_get_mount_name(name, m_pvr_info.m_pvr_mnt_name);
	return TRUE;
}

char *pvr_get_mout_prefix(void)
{
	static struct dvr_HDD_info partition_info;
	pvr_get_HDD_info(&partition_info);
	
    return (partition_info.mount_name);
}

RET_CODE pvr_set_ciplus_uri(UINT16 record_idx, record_ciplus_uri_item *item)
{	
	return pvr_mgr_ioctl(0, PVR_MGRIO_CIPLUS_URI_SET, (UINT32)item,  (0<<16)|record_idx);
}

INT32 pvr_register(UINT32 vbh_addr,UINT32 vbh_len)
{
	struct pvr_register_info info;
	struct pvr_register_info *param = NULL;

#if (defined(NEW_DEMO_FRAME) || defined(PVR_REC_TMS_PARTITION_SEPARABLE))
	param = (struct pvr_register_info *)vbh_addr;
#else
	STRCPY(info.mount_name, m_pvr_info.m_pvr_mnt_name);
	info.disk_mode = 0;
	info.disk_usage = PVR_REC_AND_TMS_DISK;
	info.init_list = 1;
	info.check_speed = 1;
	info.sync = 0;
	param = &info;
#endif

	return pvr_register_partition(param);
}

INT32 pvr_cleanup(void)
{
	return pvr_cleanup_all();
}

BOOL pvr_check_tms2rec(void)
{
	BOOL ret = FALSE;

	pvr_mgr_ioctl(0, PVR_MGRIO_CHECK_TMS2REC, (UINT32)&ret, 0);

	return ret;
}
#ifndef CNX_1X_CSD_CERT
INT32 pvr_r_request(PVR_HANDLE handle, UINT8 **addr, INT32 length)
{
	return _pvr_r_request(handle, addr, length, 0);
}

BOOL pvr_r_update(PVR_HANDLE handle, UINT32 size, UINT16 offset)
{
	return _pvr_r_update(handle, size, offset);
}

INT32 pvr_p_request(PVR_HANDLE handle, UINT8 **addr, INT32 length, INT32 *indicator)
{
	return _pvr_p_request(handle, addr, length, indicator);
}
#endif
extern struct pvr_dmx_delay *delay_control;
#ifndef CNX_1X_CSD_CERT
PVR_HANDLE pvr_get_handle_to_dmx(UINT32 dmx_id)
{
    if(delay_control != NULL)
    {
       if(*(BOOL *)(delay_control))//delay_control->start
       {
          return 255; 
       }
    }
	return PVR_IDX_2_PLY_HND(0);
}
#endif
/************************************************************/
//Summary:
//	The function copy record from a select record according to set start time and set end time.
//Description:
//	The function copy or cut record to another new record item.

RET_CODE pvr_copy_record_by_time(struct ListInfo rl_info, struct copy_param cp_param)
{
	
	if(pvr_mgr_copy(rl_info, cp_param) != RET_SUCCESS)
	{
		return RET_FAILURE;
	}
	osal_task_sleep(100); // make sure param passed successfully!!

	return RET_SUCCESS;
}
BOOL pvr_r_add_PID(PVR_HANDLE handle, UINT16 pid_nums, UINT16 *pids)
{
	if(pvr_r_get_record_all())
		return TRUE;

	return (RET_SUCCESS == pvr_mgr_ioctl(handle,PVR_ERIO_ADD_PID, (UINT32)pid_nums, (UINT32)pids));
}

BOOL pvr_clear_tms(void)
{	
	pvr_mgr_ioctl(0, PVR_ERIO_CLEAR_TMS, 0, 0);
}

struct pvr_dmx_delay
{
	BOOL start;
	PVR_HANDLE handle;
	UINT32 flag;
	UINT16 buffer_num;
	UINT16 free_num;
	struct list_head list;
	struct list_head *ptr;
	UINT32* *w, *r;
	UINT16 w_pos;
	UINT16 r_pos;
	UINT8 nim_id;
	UINT8 ts_id;
	UINT8 dmx_id;
	UINT32 delay; // measured in ms
	UINT32 r_submit_time; //last Q recieve from dmx
	UINT32 p_submit_time; //last Q submit tsg time
	UINT32 p_time_len; //last Q time len
	OSAL_ID mutex;
	UINT32 * dev_param;
};
//////////////////////////

void  pvr_dmx_delay_set_front(UINT8 i_TSA, UINT8 i_TSB)
{
     TSA=i_TSA;
     TSB=i_TSB;
}
///////////////////////////
static void delay_tsi_dmx_config(struct pvr_dmx_delay_param *param, BOOL start)
{
/*
#define TSI_TS_A 		0x01 	
#define TSI_TS_B 		0x02 

source:	Tuner->TSB->DMX0,
----------------------------------------------------
target:	TSG->TSB->DMX0,     Tuner->TSA->DMX1
      	DMX0:Parse_Pes,     DMX1:Parse_rec
----------------------------------------------------
	tsi_select(TSI_TS_A,TSI_SPI0)			        //Tuner->TSA
	tsi_select(TSI_TS_B,TSI_SPI_TSG)		        //TSG->TSB
    tsi_dmx_src_select(TSI_DMX_0, TSI_TS_B);	    //TSB->DMX0
	tsi_dmx_src_select(TSI_DMX_1, TSI_TS_A);	    //TSA->DMX1
*/
	if (start)
	{
	    UINT8 assist_ts_id = (param->ts_id == TSI_TS_A) ? TSI_TS_B : TSI_TS_A;  //param->ts_id=TSI_TS_B
    	UINT8 assist_dmx_id = 2 - param->dmx_id;
       
        tsi_dmx_src_select(param->dmx_id + 1, param->ts_id);               //The Play dmx source From TSG
        tsi_dmx_src_select(assist_dmx_id,assist_ts_id);                    //The Record dmx source From Tuner

        tsi_select(assist_ts_id, ((param->nim_id == 0) ? TSA : TSB ));     //the record dmx route

        if(param->is_using_dmx2==0)//(1==delay_control->dev_param.use_ts_gen)
        {
            tsi_mode_set(TSI_SPI_TSG, 0x83);                                        //Setting TSG IR
            tsi_select(param->ts_id, TSI_SPI_TSG);                                       // Select TS_B From TSG
        }
        
       
	}
	else // reset
	{
         tsi_select(param->ts_id, ((param->nim_id == 0) ? TSA : TSB ));     //recover the dmx route
	}
}

BOOL pvr_dmx_delay_start_ext(struct pvr_dmx_delay_param *param, struct record_prog_param *prog_info)
{
	if (param->delay == 0)
	{
		return FALSE;
	}

	delay_tsi_dmx_config(param, TRUE);
	
	if (pvr_eng_delay_start(param, prog_info) != TRUE)
	{
		return FALSE;
	}
	
	return TRUE;
}

void pvr_dmx_delay_stop()
{
	struct pvr_dmx_delay_param param;
	param.is_using_dmx2=0;
	if (TRUE == pvr_eng_delay_stop(&param))
	{
		delay_tsi_dmx_config(&param, FALSE);
	}
}

void pvr_dmx_delay_stop_ext(struct pvr_dmx_delay_param param)
{
	if (TRUE == pvr_eng_delay_stop(&param))
	{
		delay_tsi_dmx_config(&param, FALSE);
	}
}
void pvr_dmx_delay_pause(BOOL bPause)
{
	pvr_eng_delay_pause(bPause);
}

BOOL pvr_dmx_delay_start(UINT8 dmx_id, UINT8 nim_id, UINT32 delay, struct record_prog_param *prog_info)
{
	struct pvr_dmx_delay_param param;
	MEMSET(&param, 0, sizeof(struct pvr_dmx_delay_param));
	param.nim_id = nim_id;
    param.is_using_dmx2=0;
	param.ts_id  = TSI_TS_B;
	param.dmx_id = dmx_id;
	param.delay  = delay;
	return pvr_dmx_delay_start_ext(&param, prog_info);
}

UINT8 pvr_check_record_active()
{
	UINT8 ret = 0;
	
	pvr_mgr_ioctl(0, PVR_ERIO_GET_REC_CNT, (UINT32)&ret, 0);

	return ret;
}

RET_CODE pvr_p_set_preview_mode(PVR_HANDLE handle, BOOL mode)
{
	return pvr_mgr_ioctl(handle, PVR_EPIO_CHANGE_PRE_MODE, (UINT32)mode, 0);
}

#if 1//chunpin_conax6_eng
RET_CODE pvr_set_uri(PVR_HANDLE handle,conax6_URI_item_m* URI_item)
{
	return pvr_mgr_ioctl(handle, PVR_MGRIO_RECORD_SETURI, URI_item,0);
}

RET_CODE pvr_get_uri(PVR_HANDLE handle,conax6_URI_item_m* URI_item)
{
	return pvr_mgr_ioctl(handle, PVR_MGRIO_RECORD_GETURI,URI_item,0);
}

RET_CODE pvr_get_uri_cnt(UINT32 index,UINT32* wcnt)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_GETURI_CNT,index,wcnt);
}

RET_CODE pvr_get_uri_sets(UINT32 index,UINT32 base,UINT32 cnt,conax6_URI_item_m* URI_sets)
{
	return pvr_mgr_ioctl(index, PVR_MGRIO_GETURI_SETS,(base<<16)+cnt, URI_sets);
}
#endif


BOOL pvr_save_info_header(PVR_HANDLE handle, struct store_info_header* sheader)
{
	return pvr_mgr_ioctl(handle, PVR_MGRIO_SAVE_INFO_HEADER, (UINT32)sheader, 0);
}

BOOL pvr_get_info_header(PVR_HANDLE handle, struct store_info_header* sheader)
{
	return pvr_mgr_ioctl(handle, PVR_MGRIO_GET_INFO_HEADER, (UINT32)sheader, 0);
}

BOOL pvr_get_info_header_by_idx(UINT16 record_idx, struct store_info_header* sheader)
{
	return pvr_mgr_ioctl(0, PVR_MGRIO_GET_INFO_HEADER, (UINT32)sheader, (0<<16)|record_idx);
}

BOOL pvr_save_store_info(PVR_HANDLE handle, struct store_info_data_single* storeinfodata, UINT32 ptm)
{
	return pvr_mgr_ioctl(handle, PVR_MGRIO_SAVE_STORE_INFO, (UINT32)storeinfodata, ptm);
}

BOOL pvr_get_store_info(PVR_HANDLE handle, struct store_info_data* storeinfodata, UINT32 ptm)
{
	struct store_info_param storeinfo_param;

	storeinfo_param.storeinfodata=storeinfodata;
	storeinfo_param.ptm=ptm;
	
	return pvr_mgr_ioctl(handle, PVR_MGRIO_GET_STORE_INFO, &storeinfo_param, 0);
}

BOOL pvr_get_store_info_by_idx(UINT16 record_idx, struct store_info_data* storeinfodata, UINT32 ptm)
{
	struct store_info_param storeinfo_param;

	storeinfo_param.storeinfodata=storeinfodata;
	storeinfo_param.ptm=ptm;
	return pvr_mgr_ioctl(0, PVR_MGRIO_GET_STORE_INFO, &storeinfo_param, (0<<16)|record_idx);
}

UINT32 pvr_share_malloc(UINT32 size_byte, UINT32 *addr) 
{
    UINT32 size_k = (size_byte+1023)/1024;
    return pvr_mgr_share_malloc(size_k, addr)*1024;
}

void pvr_share_free(UINT32 addr)
{
    pvr_mgr_share_free(addr);
}
UINT8 pvr_get_share_count()
{ 
    return pvr_mgr_get_share_count();
}

